package com.carbonspark.gateway.auth;

import cn.dev33.satoken.context.SaHolder;
import cn.dev33.satoken.reactor.filter.SaReactorFilter;
import cn.dev33.satoken.stp.StpUtil;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.http.HttpStatus;
import reactor.core.publisher.Mono;

/**
 * 权限认证的配置器
 *
 * @author: ChickenWing
 * @date: 2023/10/28
 */
@Configuration
public class SaTokenConfigure {

    @Bean
    public SaReactorFilter getSaReactorFilter() {
        return new SaReactorFilter()
                // 拦截地址
                .addInclude("/**")
                // 排除登录和注册接口
                .addExclude("/auth/user/doLogin", "/auth/user/register")
                // 全局异常处理
                .setError(e -> {
                    // WebFlux 环境下正确的响应方式
                    SaHolder.getResponse().setHeader("Content-Type", "application/json;charset=UTF-8");
                    SaHolder.getResponse().setStatus(HttpStatus.UNAUTHORIZED.value());
                    // 返回JSON格式错误信息
                    return Mono.just("{\"code\":401,\"msg\":\"认证失败\"}");
                })
                // 鉴权方法：每次访问进入
                .setAuth(obj -> {
                    // 优先处理OPTIONS请求，把这个检查提到最前面
                    String method = SaHolder.getRequest().getMethod();
                    if (HttpMethod.OPTIONS.toString().equals(method)) {
                        // 直接返回，确保OPTIONS请求完全放行，不做任何其他检查
                        return;
                    }

                    // 只有非OPTIONS请求才会到达这里，进行登录检查
                    StpUtil.checkLogin();
                });
    }
}